HTML5 新特性: Web Worker 的创建与使用(webpack + TS 环境) 您所在的位置:网站首页 deadline worker是干嘛的 HTML5 新特性: Web Worker 的创建与使用(webpack + TS 环境)

HTML5 新特性: Web Worker 的创建与使用(webpack + TS 环境)

2023-11-30 08:45| 来源: 网络整理| 查看: 265

HTML5 新特性: Web Worker 的创建与使用(webpack + TS 环境)

文章目录 HTML5 新特性: Web Worker 的创建与使用(webpack + TS 环境)前言正文1. 基础使用1.1 Worker 定义1.2 Worker 使用 2. worker-loader2.1 webpack 配置2.2 Worker 定义2.3 Worker 使用2.4 TS 环境下的配置 3. 实践示例:计时器3.1 Worker 定义3.2 Worker 使用 结语其他资源参考连接完整代码示例

前言

我们都知道 JS 一直都是单线程的语言,并透过事件循环来提供异步操作的方法避免堵塞。

本篇来介绍一个 HTML5 新出的特性 Web Worker,它能够真正的为 JS 带来多线程的特性的一套规范,后续还有更多的妙用。本篇主要介绍基础的使用方式,以及在 TS 环境下的一些配置问题。

本篇不会对 Worker 的一些定义做过多的描述,主要偏重在实践并写到真实项目里头,相关的概念还是先参考一些博客会好一些

正文 1. 基础使用

首先第一版我们先搞最基础的版本,也就是直接调用浏览器最原始的 API 的使用方式

const worker = new Worker('sample.js')

实际上他会以同源的方式请求一个 js 文件,并加载作为 Worker 来执行

1.1 Worker 定义

接下来我们要定义一个 Worker 线程内要执行的脚本

/src/workers/test1.worker.js const PREFIX_WORKER1 = '[Worker1]'; self.onmessage = (event) => { const msg = event.data; console.log(`${PREFIX_WORKER1} receive msg in worker: ${msg}`); const greeting = `${msg} from test1.worker.js`; postMessage(greeting); }; 1.2 Worker 使用

下面我们看看项目内的用法

/src/layouts/Test1.tsx const Test1 = () => { const createWorker = () => { const worker = new Worker('workers/test1.worker.js'); worker.onmessage = (event) => { const msg = event.data; console.log(`${PREFIX_TEST1} worker.onmessage: ${msg}`); worker.terminate(); console.log(`${PREFIX_TEST1} worker finished`); }; const msg = 'Hello World'; console.log(`${PREFIX_TEST1} worker.postMessage: ${msg}`); worker.postMessage('Hello World'); }; return ( Test1 - Basic Worker /* ... */} 终止 Worker worker.terminate();

实现效果如下

2. worker-loader

第二种场景我们还可以在 webpack 中引入 Worker 的特性,甚至用起来比原生的更优雅

2.1 webpack 配置

首先是 webpack.config.js 配置要加上

module.exports = { // ... module: { rules: [ { test: /\.worker\.(js|jsx|ts|tsx)$/, exclude: /node_modules/, use: ['worker-loader', 'ts-loader'], }, ] }, // ... } 2.2 Worker 定义

接下来我们在定义一个新的 Worker

/src/workers/test2.worker.ts const PREFIX_WORKER2 = '[Worker2]'; self.onmessage = (event) => { const msg = event.data; console.log(`${PREFIX_WORKER2} receive msg in worker: ${msg}`); const greeting = `${msg} from test2.worker.ts`; postMessage(greeting); }; 2.3 Worker 使用

然后我们就可以像引入一个模块一样引入一个 Worker 脚本

/src/layouts/Test2.tsx import React from 'react'; import { PREFIX_TEST2 } from '@utils/prefixs'; import Worker from '@workers/test2.worker.ts'; const Test2 = () => { const createWorker = () => { const worker = new Worker(); worker.onmessage = (event) => { const msg = event.data; console.log(`${PREFIX_TEST2} worker.onmessage: ${msg}`); worker.terminate(); console.log(`${PREFIX_TEST2} worker finished`); }; const msg = 'Hello World'; console.log(`${PREFIX_TEST2} worker.postMessage: ${msg}`); worker.postMessage('Hello World'); }; return ( Test2 - Worker Loader "compilerOptions": { "lib": ["WebWorker", "ScriptHost", "DOM"], "allowJs": false, } }

除此之外,默认的 Worker 构造函数是需要传入一个脚本路径名的,但是在 webpack 下我们直接 import 然后就使用无参数构造函数了,所以我们需要额外建立一个类型声明

/src/types/worker.d.ts declare module '*.worker.ts' { class WebpackWorker extends Worker { constructor(); } export default WebpackWorker; }

最终效果如下

3. 实践示例:计时器

最后我们摆上一个用 Web Worker 做的时钟范例

3.1 Worker 定义 /src/workers/test3.worker.ts type MessageType = 'RESET' | 'SKIP'; let count = 0; let skipOnce = false; self.onmessage = (e: MessageEvent const { type } = e.data; switch (type) { case 'RESET': count = 0; break; case 'SKIP': skipOnce = true; break; } }; const SEC = 1000; setInterval(() => { if (skipOnce) { skipOnce = false; } else { count++; } self.postMessage({ currentTime: new Date(), count }); }, SEC); 3.2 Worker 使用 /src/layouts/Test3.tsx import React, { useEffect, useRef, useState } from 'react'; import Worker from '@workers/test3.worker.ts'; const useWorker = () => { const [currentTime, setCurrentTime] = useState(new Date()); const [count, setCount] = useState(0); const workerRef = useRef(null); useEffect(() => { const worker = new Worker(); worker.onmessage = (e) => { const { currentTime, count } = e.data; setCurrentTime(currentTime); setCount(count); }; workerRef.current = worker; }, []); const reset = () => { workerRef.current?.postMessage({ type: 'RESET' }); setCount(0); console.log(workerRef.current); }; const skip = () => { workerRef.current?.postMessage({ type: 'SKIP' }); console.log(workerRef.current); }; const terminate = () => { workerRef.current?.terminate(); console.log(workerRef.current); }; return [ { currentTime, count }, { reset, skip, terminate }, ]; }; const Test3 = () => { const [{ currentTime, count }, { reset, skip, terminate }] = useWorker(); return ( Test3 - Timer by Worker currentTime: {currentTime.toString()} count: {count} skip}>skip


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有